#include "LireXML.h"
#include "EcrireXML.h"
#include "ChoisirListe.h"
#include "Demarrage.h"
#include "ConstruitRace.h"
#include "ConstruitClasse.h"
#include "ChoixDsListe.h"
//#include "ADD.h"
#include "Joueur.h"

#include "MetaRace.h"
#include "MetaClasse.h"

//#include "ConfigurerNiveaux.h"
#include "Qlib.h"

#include "StatusCode.h"

#include "NomNbrClasse.h"
#include "EntrerTraits.h"
#include "SelectionListe.h"
#include "Progression.h"
#include "AugmenterComp.h"
#include "NomFichier.h"
#include "SortSelBase.h"
#include "MartSelBase.h"
#include "DivSelBase.h"
#include "DemanderNbr.h"

#include <QtGui/QApplication>
#include <QtCore/QStringList>
#include <QtGui/QMessageBox>

#include <QtCore/QDir>
#include <QtCore/QTextStream>

#include <QtCore/QProcess>

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <algorithm>

#include <boost/assign/list_of.hpp>

using namespace std;
using namespace boost::assign;

// Anciens programmes => fonctions

void initJoueur();
void progresJoueur();
void ajoutSorts();
void ecrireJoueur();
void Apercu();
void jumelerJoueur();

// Fonctions basiques
Race* ChoisirRace(vector< unsigned >& tab, int& pp);
Classe* ChoisirClasse(vector< unsigned >& tab, int& pp, const string& race);
void ChoisirDesavantages(Joueur *j);
void ChoisirDons(Joueur *j);
void ChoisirCompDiverses(Joueur *j);
void ChoisirMartiales(Joueur *j);
void sauverJoueur(Joueur* j);
void evolutionJoueur(Joueur *j);
Joueur* ChargerPersonnage();

// Utilitaires
bool copieFichier(const string& aCopier, const string& destination);

// Flot de sortie global
FlotMessage dout( BLANK );

int main(int argc, char* argv[])
{
  QApplication application( argc, argv );

  Demarrage Accueil;

  StatusCode sc( Accueil.demanderChoix() );

  if (sc)
    {
      switch (sc.valeur())
	{
	case 0:
	  initJoueur();
	  break;
	case 1:
	  progresJoueur();
	  break;
	case 2:
	  ajoutSorts();
	  break;
	case 3:
	  ecrireJoueur();
	  break;
	case 4:
	  Apercu();
	  break;
	case 5:
	  jumelerJoueur();
	  break;
	default:
	  return 0;
	}
    }

  return 0;
}

Joueur* ChargerPersonnage()
{
  /*Debug::empileNiveau();*/
  flotMessageGlobal() << FUNC << "ChargerPersonnage -> début" << endmsg;
  NomFichier demanderNom( QString::fromUtf8("Nom du fichier à charger :") );

  string nomfichier;

  if (!demanderNom.lireEntree(nomfichier))
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      flotMessageGlobal() << FUNC << "ChargerPersonnage -> fin" << endmsg;
      /*Debug::depileNiveau();*/
      return 0;
    }
  else
    flotMessageGlobal() << INFO << nomfichier << endmsg;

  LireXML *fichierTest = new LireXML( nomfichier );

  map< string, string > recup;

  if ( ! fichierTest -> estOK() )
    {
      flotMessageGlobal() << ERR << "Erreur de lecture" << endmsg;
      flotMessageGlobal() << FUNC << "ChargerPersonnage -> " << endmsg;
      /*Debug::depileNiveau();*/
      return 0;
    }

  fichierTest -> getInformation( recup );

  delete fichierTest;

  map<std::string, std::string>::const_iterator it,
    Begin(recup.begin()),
    End(recup.end());
  
  for (it = Begin; it != End; it++)
    flotMessageGlobal() << LINFO << it -> first << " - " << it -> second << endmsg;

  Joueur *j = new Joueur( &recup );

  flotMessageGlobal() << FUNC << "ChargerPersonnage -> fin" << endmsg;
  /*Debug::depileNiveau();*/
  return j;
}

void sauverJoueur(Joueur* j)
{
  /*Debug::empileNiveau();*/
  flotMessageGlobal() << FUNC << "sauverJoueur -> début" << endmsg;
  NomFichier demanderNom( QString::fromUtf8( "Nom du fichier à créer :" ),
			  true );

  string nomfichier;

  StatusCode sc( demanderNom.lireEntree( nomfichier ) );

  if ( ! sc )
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      flotMessageGlobal() << FUNC << "sauverJoueur -> fin" << endmsg;
      /*Debug::depileNiveau();*/
      return;
    }
  else
    flotMessageGlobal() << INFO << nomfichier << endmsg;

  EcrireXML testEcriture( nomfichier, j, ( sc.valeur() == 0 ) );

  testEcriture.ecrirePerso();

  flotMessageGlobal() << FUNC << "sauverJoueur -> fin" << endmsg;
  /*Debug::depileNiveau();*/
}

void Apercu()
{
  /*Debug::empileNiveau();*/
  flotMessageGlobal() << FUNC << "Apercu -> début" << endmsg;
  Joueur *grobill;

  grobill = ChargerPersonnage();

  if ( grobill == 0 )
    {
      flotMessageGlobal() << ERR << "Ne peut pas réaliser l'aperçu" << endmsg;
      flotMessageGlobal() << FUNC << "Apercu -> fin" << endmsg;
      /*Debug::depileNiveau();*/
      return;
    }

  stringstream info;

  grobill -> information( info );

  QString affichage( QString::fromUtf8(info.str().c_str()) );

  QMessageBox mess(QMessageBox::NoIcon, QString::fromUtf8( "Aperçu" ),
		   affichage);

  mess.exec();

  delete grobill;

  flotMessageGlobal() << FUNC << "Apercu -> fin" << endmsg;
  /*Debug::depileNiveau();*/
}

void jumelerJoueur()
{
  /*Debug::empileNiveau();*/
  flotMessageGlobal() << FUNC << "jumelerJoueur -> début" << endmsg;
  Joueur *joueur;

  joueur = ChargerPersonnage();

  if ( joueur == 0 )
    {
      flotMessageGlobal() << ERR << "Ne peut pas charger le joueur" << endmsg;
      flotMessageGlobal() << FUNC << "jumelerJoueur -> fin" << endmsg;
      /*Debug::depileNiveau();*/
      return;
    }


  if ( joueur -> racePtr() -> type() != "Humain")
    {
      flotMessageGlobal() << WARN << "Ce personnage ne peut pas jumeler, ce n'est pas un humain"
		<< endmsg;
      flotMessageGlobal() << FUNC << "jumelerJoueur -> fin" << endmsg;
      /*Debug::depileNiveau();*/
      return;
    }

  vector< unsigned > traits;
  int pp(0);

  traits.assign( joueur -> traits() -> begin(), joueur -> traits() -> end() );

  Classe *nouvelleClasse = ChoisirClasse( traits, pp,
					 joueur -> racePtr() -> type() );

  if (nouvelleClasse != 0)
    joueur -> ajoutClasse( nouvelleClasse );

  sauverJoueur( joueur );

  delete joueur;

  flotMessageGlobal() << FUNC << "jumelerJoueur -> fin" << endmsg;
  /*Debug::depileNiveau();*/
}

void initJoueur()
{
  /*Debug::empileNiveau();*/
  flotMessageGlobal() << FUNC << "initJoueur -> début" << endmsg;
  NomNbrClasse initialisation;

  QString Nom;
  unsigned classesNbr;

  if ( initialisation.demander( &Nom, &classesNbr ) )
    flotMessageGlobal() << INFO << Nom.toStdString() << ' ' << classesNbr << " classes" << endmsg;
  else
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      flotMessageGlobal() << FUNC << "initJoueur -> fin" << endmsg;
      /*Debug::depileNiveau();*/
      exit( 0 );
    }

  vector< unsigned > traits;

  EntrerTraits entrerTraits;

  StatusCode sc( entrerTraits.demanderTraits( traits ) );

  if ( ! sc )
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      flotMessageGlobal() << FUNC << "initJoueur -> fin" << endmsg;
      /*Debug::depileNiveau();*/
      exit( 0 );
    }

  int ppCreation(0);

  Race *race;
  race = ChoisirRace( traits, ppCreation );

  if (race == 0)
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      flotMessageGlobal() << FUNC << "initJoueur -> fin" << endmsg;
      /*Debug::depileNiveau();*/
      exit( 0 );
    }

  // Appliqur les ajustements raciaux aux traits !
  race -> appliquerAjustements( traits );

  vector< Classe* > vec;
  Classe *ptr;
  
  for (unsigned i(0); i < classesNbr; i++)
    {
      ptr = ChoisirClasse( traits, ppCreation, race -> type() );
      if ( ptr == 0 )
	return;
      
      if ( ptr -> forceExceptionnelle( traits[ 0 ] ) )
	{
	  DemanderNbr forException( "Score de force exceptionnelle",
				    "Entrer '100' pour 100, et pas '00'",
				    1, 100 );
	  
	  StatusCode except( forException.Nbr() );
	  if ( except )
	    traits[6] = except.valeur();
	}

      ptr -> appliquerModif( race -> type(), traits[ 1 ] );
      vec.push_back( ptr );
    }

  // if ( traits[6] != 0 )
  //   {
  //     for (unsigned i(0); i < classesNbr; i++)
  // 	vec[ i ] -> setTrait( 6, traits[ 6 ] ) ;
  //   }

  Joueur* joueur;
  joueur = new Joueur( vec.front(), race, Nom.toUtf8().constData() );

  joueur -> setTraits( traits );

  for (unsigned i(1); i < classesNbr; i++)
    joueur -> ajoutClasse( vec[i] );

  unsigned ajoutPP(0);

  vector< TypeClasse >::const_iterator Debut, Fin;

  flotMessageGlobal() << WARN << "Vérifier les PP donnés pour la création de chaque classe"
	    << endmsg
	    << "A la limite mettre une méthode dans Joueur" << endmsg;

  /*
   * Permet de savoir si on crée le perso avec expérience nulle ou si
   * on a déjà effectué des quêtes. Si oui, alors il ne faut pas
   * appliquer le bonus dû à l'intelligence au nombre de PP.
   */
  bool justeCree( true );

  /**
   * @todo Vérifier si le nombre de PP pour un perso est bien le
   * maximum des Classes qu'il a ou alors la somme. Implémentation
   * courante : max.
   */
  for (unsigned i(0); i < classesNbr; i++)
    {
      justeCree &= ( joueur -> classePtr( i ) -> xp() <= 1 );
      Debut = joueur -> classePtr(i) -> tc() -> begin();
      Fin   = joueur -> classePtr(i) -> tc() -> end();
      if ( joueur -> classePtr(i) -> niveau() == 1 &&
	   find( Debut, Fin, Combattants ) != Fin )
	ajoutPP = max( 6u, ajoutPP );
      else if ( joueur -> classePtr(i) -> niveau() == 1 &&
		find( Debut, Fin, Roublards ) != Fin )
	ajoutPP = max( 6u, ajoutPP );
      else if ( joueur -> classePtr(i) -> niveau() == 1 &&
		find( Debut, Fin, Pretres ) != Fin )
	ajoutPP = max( 8u, ajoutPP );
      else if ( joueur -> classePtr(i) -> niveau() == 1 &&
		find( Debut, Fin, Magiciens ) != Fin )
	ajoutPP = max( 8u, ajoutPP );
    }

  /*
   * Faire une fonction qui prend le Joueur et le bool justeCree, qui
   * détermine comment il faut demander les PVs (par Classe
   * maintenant!) et les PPs.
   */

  DemanderNbr *PVs( 0 ), *PPs( 0 );

  if ( justeCree )
    {
      ppCreation += ajoutPP;

      joueur -> setPP( ppCreation, justeCree );

      PVs = new DemanderNbr( "Nombre de PV",
			     "Entrer le nombre de PV, sans éventuel\nbonus de Constitution.",
			     1, 12);
    }
  else
    {
      PVs = new DemanderNbr( "Nombre de PV",
			     "Entrer le nombre de PV total du personnage.",
			     1, 120);

      PPs = new DemanderNbr( "Nombre de PP",
			     "Entrer le nombre de PP.",
			     1, 120);
    }

  flotMessageGlobal().setNiveauCourant( LINFO );

  joueur -> information( flotMessageGlobal().stream() );

  ChoisirDesavantages( joueur );

  ChoisirDons( joueur );
  
  ChoisirCompDiverses( joueur );

  ChoisirMartiales( joueur );

  sauverJoueur( joueur );

  delete joueur;

  flotMessageGlobal() << FUNC << "initJoueur -> " << endmsg;
  /*Debug::depileNiveau();*/
}

Classe* ChoisirClasse(vector< unsigned >& tab, int& pp, const string& race)
{
  vector<string> classes = list_of ("Guerrier") ("Paladin") ("Rôdeur")
    ("Clerc") ("Druide") ("Mage") ("Spécialiste") ("Barde") ("Voleur");

  vector<string> aides = list_of
    ("Les guerriers sont des experts en armes, et sont souvent des maîtres\nen matière de tactique et statégie.")
    ("Le paladin est un guerrier noble et héroïque - c'est souvent le\nchevalier en armure brillante présent dans la littérature.")
    ("Le rôdeur est un chasseur et un coureur des bois qui vit en\npleine nature.")
    ("Un prêtre est le fidèle d'une divinité donnée, qui fait souvent\npartie d'un groupe (ou panthéon) de divinités. Il agit de manière conforme aux\ndésirs de son dieu, et utilise ses pouvoirs et talents pour aider les autres et\naugmenter l'influence de sa religion.")
    ("Les druides sont les conseillers des chefs de tributs. Il croient\nque la terre est mère de toute chose et ils la vénèrent, ainsi que le soleil,\nla lune et certaint arbres comme des divinités.")
    ("Les magiciens controlent une énergie considérable et sont des\nennemis dangereux. Le pouvoir de contrôler cette énergie\nmagique vient de leur esprit.")
    ("Les mages spécialisé, comme les illusionnistes, sont ceux qui ont\nchoisi de concentrer leurs études dans une école de magie particulière.")
    ("Un barde doit avoir la langue agile, le coeur léger et le pied sûr.\nC'est un touche-à-tout mais il n'est maître dans aucune compétence. Ce sont\ngénéralement des chanteurs ou musiciens doués.")
    ("La profession de voleur n'est pas la plus honorable. Cependant\nde nombreux héros populaires étaient des voleurs, dérobant\naux riches et aux corrompus pour donner aux pauvres.\nLe voleur peut être une figure romantique ou fanfaronne.");

  ChoisirListe choixClasse("Choix de la classe :", &classes, &aides);

  StatusCode sc( choixClasse.demanderChoix() );
  
  if ( sc )
    {
      cerr << "Choix OK" << endl;
      flotMessageGlobal() << DEBUG << "Choisi " << sc.valeur() << endmsg;
    }
  else
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      return 0;
    }

  ConstruitClasse *construitClasse;

  Classe *classe;

  // switch( sc.valeur() )
  //   {
  //   case 0:
  //     classe = new Guerrier( tab, true, race);
  //     break;
  //   case 1:
  //     classe = new Paladin( tab, true, race);
  //     break;
  //   case 2:
  //     classe = new Rodeur( tab, true, race);
  //     break;
  //   case 3:
  //     classe = new Clerc( tab, true, race);
  //     break;
  //   case 4:
  //     classe = new Druide( tab, true, race);
  //     break;
  //   case 5:
  //     classe = new Mage( tab, true, race);
  //     break;
  //   case 6:
  //     classe = new Spec( tab, true, race);
  //     break;
  //   case 7:
  //     classe = new Barde( tab, true, race);
  //     break;
  //   case 8:
  //     classe = new Voleur( tab, true, race);
  //     break;
  //   default:
  //     flotMessageGlobal() << WARN << "Classe inconnue" << endmsg;
  //     return 0;
  //   }

  cerr << "Déclaration de la MetaClasse" << endl;
  
  MetaClasse modele( classes[ sc.valeur() ] );

  cerr << "MetaClasse initialisé" << endl;

  sc = modele.lireFichier();

  cerr << "MetaClasse utilisé" << endl;

  if ( ! sc )
    {
      flotMessageGlobal() << ERR << sc.message() << endmsg;
      return 0;
    }
  else
    {
      cerr << "Choix OK" << endl;
      flotMessageGlobal() << DEBUG << "Choisi " << sc.valeur() << endmsg;
    }

  cerr << "Tentative de création de l'objet final" << endl;

  classe = modele.creerObjet();

  //cerr << "Classe créée, ajout des traits" << endl;

  //classe -> setTraits( tab );

  //cerr << "Traits OK, on passe à la vérification des prérequis" << endl;

  sc = classe -> prerequisOK( race, tab );

  if ( ! sc )
    {
      delete classe;
      flotMessageGlobal() << ERR << sc.message() << endmsg;
      return 0;
    }

  construitClasse = new ConstruitClasse( classe, race, tab, pp );

  sc = construitClasse -> classeChoisie();

  pp = sc;

  delete construitClasse;

  if (sc)
    return classe;
  else
    return 0;
}

Race* ChoisirRace(vector< unsigned >& tab, int& pp)
{
  /*Debug::empileNiveau();*/

  vector<string> races = list_of ("Humain") ("Demi-Elfe") ("Demi-Ogre")
    ("Demi-Orque") ("Elfe") ("Gnome") ("Hobbit") ("Nain");

  vector<string> aides = list_of
    ("Les Humains sont la race la plus répandue. La variété des\nvisages, carnations et pilosité est très grande.")
    ("Les Demi-Elfes sont les descendant de parent Elfe et Humain. Leur\ntaille moyenne est 1.70 m et ils pèsent environ 75 kg. Ils ont\ndes caractéristiques de leurs deux parents.")
    ("Cet hybride résulte de l'union de parents Humain et Ogre. Leur\ntaille moyenne est de 2.10 - 2.40 m. Ils ont un teint rougeaud,\ndes cheveux et des yeux sombres. Ils ont l'air d'énormes Humains.")
    ("Un autre exemple d'hybride, les Demi-Orques sont le fruit de\nl'union de parent Orque et Humain. De taille similaire à un\nDemi-Elfe, les Demi-Orques ressemblent généralement suffisamment\nà leur parent Humain pour pouvoir passer pour un Humain en\npublic. Leur carnation va de pêche à olive, ou encore\nbasané. Leurs cheveux peuvent être blonds, roux, bruns, gris ou\nnoirs.")
    ("Les Elfes tendent à être plus grands que les Nains et plus petits\net minces que les Humains. Leurs traits sont anguleux et finement\nciselés et bien qu'ils peuvent sembler minces et faibles, ils\nsont en fait rapides et forts. Lorsque les ciconstances\nl'exigent, les Elfes peuvent être de féroces guerriers, prenant\ntoutes les mesures pour se défendre et protéger leur foyer et\nleurs amis.\n\nLa plupart des Elfes font entre 1.50 et 1.65 m et pèsent environ\n55 kg. Ils préfèrent vivre en milieu naturel, comme les forêts\nisolées et bosquets. Ils sont chaotiques par nature et les autres\nraces les considèrent comme étant frivoles et distants.\n\nLes Elfes sont dotés d'une vie extrèmement longue, en moyenne\n1'200 ans. Cela peut expliquer certaines de leurs attitudes - la\nvie doit être vécue lentement et appréciée; ne jamais se\nprécipiter pour accomplir quelquechose; il y a plein de temps\npour chaque activité. Les Elfes aiment chanter, danser et chercher\nla beauté à l'état brute dans tout ce qu'ils voient.\n\nPeut-être à cause de leur longévité, les Elfes se font\ndifficilement des amis parmis les races à la vie plus\ncourte. Certains Elfes ne veulent pas prendre la peine de devenir\nproche avec un Humain, puisque ces amis meureront de viellesse\ntrès bientôt. Cependant les Elfes qui se font des amis en dehors\nde leur race traitent leurs camarades en égaux. Les amis - et les\nennemis - ne sont jamais oubliés.\n\nLes Elfes sont fascinés par la magie et vouent leur temps et leur\nénergie à étudier les arcanes de la magie. Même de puissants\nmages humains respectent et admirent la compréhension de la magie\nqu'ont les Elfes.")
    ("Apparentés aux Nains, les Gnomes sont plus petits - en moyenne 90\n- 105 cm et pèsent environ 35 kg. Les Gnomes ont la peau très\nbronzée ou brune avec des cheveux blancs. Leur trait distinctif\nest leur nez, duquel ils tirent une grande fierté. Pour une\nquelconque raison, tous les Gnomes ont de très grands nez - en\ncomparaison de leurs autres caractéristiques faciales.\n\nL'espérance de vie moyenne d'un Gnome est de 350 ans. Les Gnomes\ntendent à vivre dans les prairies alpines et les forêts\nrocailleuses. Leur petite taille les rends méfiant à l'égard des\nraces plus grandes, mais les ils ne sont pas hostiles à moins que\nle représentant des \"Grandes Gens\" ne soit malfaisant.\n\nLes Gnomes sont bien moins renfrognés que leurs cousins Nains,\nils ont un sens de l'humour aiguisé. Bien des gens - des Gnomes\npour la plupart - disent que les Gnomes ont élevés les jeux de\nmots au rang d'un art. Les Gnomes aiment également les êtres\nvivants et les objets finement ouvragés de tout type. Mais ils\naiment par-dessus tout les gemmes et la joaillerie et sont\nconsidérés par beaucoup comme les meilleurs coupeurs de gemmes et\njoailliers au monde.")
    ("La plupart des Hobbits font aux alentours de 90 cm de haut et\npèsent de 30 à 35 kg. Ils sont généralement rondelets, avec des\nvisages ronds, larges et souvent fleuris. Ils ont les cheveux\nbouclés et ont également des poils bouclés sur leurs pieds, qu'il\nont généralement nus. L'espérance de vie moyenne d'un Hobbit est\nde 150 ans.\n\nLes Hobbits sont un peuple robuste est industrieux, généralement\ncalme et pacifique. Ils apprécient le confort matériel et loin\nd'être ambitieux, sont amicaux et ouverts. Leurs foyers sont des\nterriers bien aménagés et la plupart de leurs travaux sont\neffectués en plein air, au soleil. Les Hobbits se trouvent mêlés\naux autres races, y compris les Humains et peuvents être trouvés\ndans presque toutes les civilisations.")
    ("Les Nains sont une race petite et trapue, dont la taille moyenne\nest de 1.20-1.35 m. Ils ont souvent une carnation colorée, des\ncheveux foncés et des yeux sombres et perçants. L'espérance de\nvie naturelle d'un nain est de 350 ans. Ils sont généralement\nsérieux, peu enclins aux frivolités : ils préfèrent une bonne\njournée de dur labeur. Bien qu'ils soient parfois considérés\ncomme taciturnes, très peu doute du courage et de la bravoure des\nNains. Ils ont de faibles talents pour la magie, mais excellent\ndans le combat, l'art de la guerre et les arts relatifs à\nl'ingénierie.\n\nLes Nains habitent généralement dans les collines et régions\nmontagneuses, car ils aiment la solidité de la terre et du roc\ndans lesquels ils creusent leurs maisons souterraines. Les Nains\nminent pour les métaux précieux et les gemmes. Ils sont\nparticulièrement friands de l'or.\nA cause de leur résistance à la magie, les Nains on des\ndifficultés à utiliser des objets enchantés.");

  ChoisirListe choixRace("Choix de la race :", &races, &aides);

  StatusCode sc( choixRace.demanderChoix() );

  if ( sc )
    {
      flotMessageGlobal() << DEBUG << "Choisi le bla bla num " << sc.valeur() << endmsg;
    }
  else
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      return 0;
    }

  ConstruitRace *construitRace = 0;

  Race *race = 0;

  MetaRace modele( races[ sc.valeur() ] );

  sc = modele.lireFichier();

  if ( ! sc )
    {
      flotMessageGlobal() << ERR << sc.message() << endmsg;
      /*Debug::depileNiveau();*/
      return 0;
    }

  race = modele.creerObjet();

  sc = race -> rempliPrerequis( tab );

  if ( !sc )
    {
      flotMessageGlobal() << ERR << sc.message() << " (" << sc.code()
	      << " est la limite et la valeur est " << tab[ sc.valeur() ]
	      << ")" << endmsg;
      /*Debug::depileNiveau();*/
      return 0;
    }

  construitRace = new ConstruitRace( race );

  sc = construitRace -> raceChoisie();

  // Attention, normalement ça marche mais pas 100% sûr.
  pp = sc;

  flotMessageGlobal() << DEBUG << "Reste " << pp << " pp" << endmsg;

  /*Debug::depileNiveau();*/

  if (sc)
    return race;
  else
    return 0;
}

void ChoisirDesavantages(Joueur *j)
{
  vector<CapaciteRaciale> vecDesavantages;

  unsigned nbrDesavantages(j -> listeDesavantages(vecDesavantages));

  vector<string> vecStr;
  vector<int> vecCout;

  for (unsigned i(0); i < nbrDesavantages; i++)
    {
      vecStr.push_back(vecDesavantages[i].nom());
      vecCout.push_back(-vecDesavantages[i].prix());
    }
  
  SelectionListe desavantages(nbrDesavantages, &vecStr[0], &vecCout[0],
			      0, "Désavantages");

  vector<unsigned> tmp;

  StatusCode selDes( desavantages.Choisir(tmp) );

  if ( selDes )
    {
      flotMessageGlobal() << DEBUG << tmp.size() << " désavantages choisis, OK" << endmsg;
      if (!tmp.empty())
	flotMessageGlobal() << DEBUG << "Premier desavantage " << tmp.front() << endmsg;
      j -> setDesavantages(tmp);
      j -> setPP( selDes.valeur() + j -> nbrPP() );
    }
  else
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      exit( 0 );
    }
}

void ChoisirDons(Joueur *j)
{
  vector<CapaciteRaciale> vecDons;

  unsigned nbrDons(j -> listeDons(vecDons));

  vector<string> vecStr;
  vector<int> vecCout;

  for (unsigned i(0); i < nbrDons; i++)
    {
      vecStr.push_back(vecDons[i].nom());
      vecCout.push_back(vecDons[i].prix());
    }

  SelectionListe dons(nbrDons, &vecStr[0], &vecCout[0],
		      j -> nbrPP(), "Dons");

  vector<unsigned> tmp;

  StatusCode selDons( dons.Choisir(tmp) );

  if ( selDons )
    {
      flotMessageGlobal() << DEBUG << tmp.size() << " dons choisis, OK" << endmsg;
      j -> setDons(tmp);
      j -> setPP( selDons.valeur() );
    }
  else
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      exit( 0 );
    }
}

void ChoisirCompDiverses(Joueur *j)
{
  const string* Categories;
  unsigned nbrCategories;
  
  Categories = j -> listeCategories(nbrCategories);

  DivSelBase test(nbrCategories, Categories, j);

  vector<unsigned> choix;

  if ( test.compDivSelection(choix) )
    {
      flotMessageGlobal() << DEBUG << "OK, choix fait" << endmsg;
      j -> initDiverses(choix);
    }
  else
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      exit( 0 );
    }

}

void ChoisirMartiales(Joueur *j)
{
  MartSelBase Larges( j );

  vector<unsigned> choix;

  Larges.Choisir(choix);
}

void progresJoueur()
{
  Joueur *joueur;

  joueur = ChargerPersonnage();

  if ( joueur == 0 )
    {
      flotMessageGlobal() << ERR << "Ne peut pas charger le joueur" << endmsg;
      return;
    }

  evolutionJoueur( joueur );
  
  sauverJoueur( joueur );

  delete joueur;
}

void ajoutSorts()
{
  Joueur *joueur;

  joueur = ChargerPersonnage();

  if ( joueur == 0 )
    {
      flotMessageGlobal() << ERR << "Ne peut pas charger le joueur" << endmsg;
      return;
    }

  vector<unsigned> sorts;

  // debug
  const vector< Sort > *ptr;
  unsigned cl, nb, i;

  cl = joueur -> nbrClasses();

  for (i = 0; i < cl; i++)
    {
      ptr = joueur -> sorts(nb, i);
      flotMessageGlobal() << LFUNC << "Classe  " << i << " a " << nb << " sorts" << endmsg;
    }
  // debug

  if (joueur -> niveauMagie() > 0)
    {
      SortSelBase test(joueur);
  
      if (test.sortsSelectionnes(sorts))
	{
	  for (unsigned i(0); i < sorts.size(); i++)
	    flotMessageGlobal() << LINFO << sorts[i] << ' ';
	  flotMessageGlobal() << LINFO << endmsg;
	}
    }
  else
    {
      QMessageBox mess;
      mess.setText( QString::fromUtf8("Votre personnage ne peut (actuellement) pas lancer\nde sorts de mage.\nVotre niveau est peut-être trop bas, ou alors\nvotre classe ne vous le permet pas.") );
      mess.exec();
    }

  // debug
  for (i = 0; i < cl; i++)
    {
      ptr = joueur -> sorts(nb, i);
      flotMessageGlobal() << LINFO << "Classe  " << i << " a " << nb << " sorts" << endmsg;
    }
  // debug

  sauverJoueur(joueur);

  delete joueur;
}

void ecrireJoueur()
{
  Joueur *joueur;

  joueur = ChargerPersonnage();

  if ( joueur == 0 )
    {
      flotMessageGlobal() << ERR << "Ne peut pas charger le joueur" << endmsg;
      return;
    }

  string chemin("/Feuilles/" + joueur -> convertNom());

  QString qChemin( QDir::currentPath() + QString::fromUtf8(chemin.c_str()) );

  qChemin.replace(  QString(" "), QString("") );
  qChemin.replace(  QString("\'"), QString("") );
  qChemin.append( "/" );

  QDir dossier( qChemin );

  if (!dossier.exists())
    {
      if (dossier.mkdir( qChemin ))
	{
	  flotMessageGlobal() << INFO << "Création du dossier " << qChemin.toStdString() << endmsg;

	  // On copie le fichier Perso.tex
	  
	  copieFichier( "Joueur0/Perso.tex", qChemin.toStdString() + "Perso.tex" );
	}
      else
	{
	  flotMessageGlobal() << ERR << "Erreur lors de la création de " << qChemin.toStdString()
		  << endmsg;
	  return;
	}
    }
  else
    {
      QFile fichier( qChemin + QString("Perso.tex") );

      if (!fichier.exists())
	{
	   copieFichier( "Joueur0/Perso.tex",
			 qChemin.toStdString() + "Perso.tex" );
	}
    }

  joueur -> ecrireTex( true );

  QProcess *script = new QProcess;

  QStringList args;

  args << "tmp.sh";

  script -> execute( QString("sh"), args );

  args.clear();
  /*
   * Faire ça un peu plus malin : regarder la dernière ligne de
   * Joueur0/Finition.sh
   */
  QFile scriptFinition( QString("Joueur0/Finition.sh") );
  if( ! scriptFinition.open( QIODevice::ReadOnly ) )
    {
      flotMessageGlobal() << ERR << "Ne peut pas lire le fichier Joueur0/Finition.sh" << endmsg;
      return;
    }
  
  QTextStream lire( &scriptFinition );
  QString ligne;
  while ( ! lire.atEnd() )
    {
      ligne = lire.readLine();
      if ( ligne.indexOf( QString( "&" ) ) != -1 )
	args = ligne.split( " ", QString::SkipEmptyParts );
    }
  /*
   * Trouver un moyen d'obtenir la dernière ligne du fichier, extraire
   * le nom du programme et le nom du fichier.
   */

  if ( args.empty() )
    {
      flotMessageGlobal() << ERR << "Pas possible de trouver la commande pour visualiser!"
	      << endmsg;
      return;
    }

  ligne = args[0];
  args.removeAt( 0 );

  args[0] = qChemin + args[0];
  args.removeAt( 1 );

  script -> start( ligne, args );

  script -> deleteLater();
}

void evolutionJoueur(Joueur *j)
{
  /*Debug::empileNiveau();*/
  flotMessageGlobal() << FUNC << "evolutionJoueur -> début" << endmsg;
  Progression gain( j );

  StatusCode sc( gain . pointsGagnes() );

  if (! sc.etat() )
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      flotMessageGlobal() << FUNC << "evolutionJoueur -> fin" << endmsg;
      /*Debug::depileNiveau();*/
      exit( 0 );
    }

  const string* Categories;
  unsigned nbrCategories;
  
  Categories = j -> listeCategories( nbrCategories );

  flotMessageGlobal() << DEBUG << "nbr catégories " << nbrCategories << endmsg;

  DivSelBase test(nbrCategories, Categories, j);

  vector<unsigned> choix, aAjouter;

  if ( test.compDivSelection(choix) )
    {
      flotMessageGlobal() << DEBUG << "OK, choix fait" << endmsg;
      j -> ajouterDiverses(choix);
    }
  else
    {
      flotMessageGlobal() << ERR << "Abandon" << endmsg;
      flotMessageGlobal() << FUNC << "evolutionJoueur -> fin" << endmsg;
      /*Debug::depileNiveau();*/
      exit( 0 );
    }

  AugmenterComp progres(j);

  sc = progres . choixFait();

  if ( !sc )
    {
      flotMessageGlobal() << WARN << "Annulation des modifications" << endmsg;
    }

  MartSelBase martiales( j );

  vector< unsigned > martChoix;

  sc = martiales . Choisir( martChoix );

  if ( !sc )
    {
      flotMessageGlobal() << WARN << "Annulation des modifications" << endmsg;
    }

  flotMessageGlobal() << FUNC << "evolutionJoueur -> fin" << endmsg;
  /*Debug::depileNiveau();*/
}


bool copieFichier(const string& aCopier, const string& destination)
{
  QFile input( aCopier.c_str() );
  if(!input.open( QIODevice::ReadOnly ))
    { 
      // error
      return false;
    }
  QFile output( destination.c_str() );
  if(!output.open( QIODevice::WriteOnly ))
    {
      // error
      return false;
    }
  QTextStream inputstream(&input);
  QTextStream outputstream(&output);
  outputstream << inputstream.readAll();
  output.close();
  input.close();
  return true;
}
